var port = 8080;
var keys = new Keys();

var enemies = [];
var NPCs = [];

var canvas;
var miniCanvas;
var viewCtx;

var miniCtx;

var attackCanvas;
var attackCtx;

var playerPosition = [400, 400];
var playerNick = "";

var trees, malpoludy, smoki, krowy, handlarze, stawy, kopalnie;

var otherPlayers = {};

var map = {
    w : 0, h : 0,
    trees : [], malpoludy : [], smoki : [], kopalnie : [],
    stawy : [], krowy : [], handlarze : [], enemies : []
};

var socket;

var level = 1;

var whichCharacter = 0;

var character;

var leftOffset = 230;

var mouseX;
var mouseY;

var zloto = 10;
var startoweZloto = 10;

var gra = false;

var canvasWidth = 800;
var canvasHeight = 800;

var offX = 0;
var offY = 0;

var handel = false;
var dojenie = false;
var rabanie = false;
var lowienie = false;
var wydobywanie = false;
var zbieranieMonet = false;

var hoverDrzewo = false;
var hoverKopalnia = false;
var hoverStaw = false;
var hoverKrowa = false;
var hoverHandlarz = false;
var hoverMonety = false;

var czyHandel = false;

var ctrlDown = false;

var coins = [];
var strzal = [];

var stats;

var framePos = [0, 0];

var pokazywanieWynikow = false;

var player;

var dxStrzalu = 0;
var dyStrzalu = 0;

function ustawCanvas(id, w, h) {

    var _canvas = document.getElementById(id);
    _canvas.width = w;
    _canvas.height = h;
    return _canvas;
}

function ustawPostacie() {

    var i;
    enemies = [];
    for (i = 0; i < smoki.length; i++) {
        enemies.push(new Enemy(smoki[i], getAttr("smok")));
    }

    for (i = 0; i < malpoludy.length; i++) {
        enemies.push(new Enemy(malpoludy[i], getAttr("malpolud")));
    }

    NPCs = [];
    for (i = 0; i < krowy.length; i++) {

        NPCs.push(new NPC(krowy[i], "krowa"));
    }

    for (i = 0; i < handlarze.length; i++) {

        NPCs.push(new NPC(handlarze[i], "handlarz"));
    }
}

function ustawObiekty() {

    trees = map.trees;
    smoki = map.smoki;
    malpoludy = map.malpoludy;
    krowy = map.krowy;
    handlarze = map.handlarze;
    stawy = map.stawy;
    kopalnie = map.kopalnie;
}

function etykieta(id, text) {
    $("#" + id).html(text);
}

function ustaw() {

    ustawObiekty();
    ustawPostacie();

    etykieta("mapa", "mapa: " + map.w + " x " + map.h + "");

    canvas = ustawCanvas('canvas', canvasWidth, canvasHeight);
    viewCtx = canvas.getContext('2d');

    miniCanvas = ustawCanvas('miniCanvas', 100, 100);
    miniCtx = miniCanvas.getContext('2d');

    attackCanvas = ustawCanvas('attackCanvas', 40, 40);
    attackCtx = attackCanvas.getContext('2d');

    character = characters[whichCharacter];

    resizeCanvas();

    // odbiera od serwera dane dotyczące nowej mapy
    socket.on('newLevel', function (data) {

        level++;
        etykieta("komunikat", "Poziom:" + level);
        map = data;

        resizeCanvas();

        // wczytujemy wartości z wygenerowanej mapy

        ustawObiekty();
        ustawPostacie();

        etykieta("mapa", "mapa: " + map.w + " x " + map.h + "");
        etykieta("level", "Poziom: " + level);

        // ustawiamy gracza

        player.setPos(400, 400);
    });

    socket.on('otherPlayers', function (data) {

        otherPlayers = data;
    });

    socket.on('teamInfo', function (data) {

        stats = data;

        etykieta("dobroGraczy", "Liczba graczy: " + stats[0]);
        etykieta("dobroDosw", stats[1]);
        etykieta("dobroZloto", stats[2]);
        etykieta("dobroZycie", stats[3]);

        etykieta("zloGraczy", "Liczba graczy: " + stats[4]);
        etykieta("zloDosw", stats[5]);
        etykieta("zloZloto", stats[6]);
        etykieta("zloZycie", stats[7]);
    });

    socket.on('enemiesData', function(data) {

        for (var i = 0; i < data.length; i++) {

            enemies[i].setMove(data[i]);
        }
    });

    socket.on('loseHP', function(nick) {

        if (player.loseHP() && gra) {

            gra = false;
            socket.emit('killer', nick);

            var sojusznicy = (player.strona == STRONA.DOBRO) ? listaDobra : listaZla;

            socket.emit('utrataDosw', sojusznicy);

            etykieta("komunikat", "Przegrales");
            setTimeout(function () {
                player.restart();

                gra = true;
            }, 3000);
        }
    });

    socket.on('gainExp', function(ile) {
        player.zyskajDoswiadczenie(ile);
    });

    socket.on('utrataDosw', function(d) {

        player.utracDoswiadczenie();
    });

    socket.on('koniecGry', function(wynik) {

        if (wynik == 0) {
            alert('KONIEC GRY, REMIS');
        } else if (wynik == 1) {
            alert('KONIEC GRY, WYGRAŁO DOBRO');
        } else {
            alert('KONIEC GRY, WYGRAŁO ZŁO');
        }

        gra = false;
        startMenu();
    });

    socket.on('miniaturka', function(data) {

        ustawMinicanvas(IMG[data.nazwa]);
        etykieta("enemyHP", "Zycie: " + data.zycie);
    });

    socket.on('enemyHP', function(data) {

        var i = data[0];
        var wartosc = data[1];
        enemies[i].ustawZycie(wartosc);
    });
}

function init() {

    socket = io.connect('http://192.168.1.102:' + port);
    setEventHandlers();
    socket.on('mapa', function (data) {

        map = data;
    });
}

// dodaje obsługę handlerow klawiatury
var setEventHandlers = function () {

    window.addEventListener("keydown", onKeydown, false);
    window.addEventListener("keyup", onKeyup, false);
    window.addEventListener("resize", resize, false);
};

function resize(e) {

    resizeCanvas();
}

function resizeCanvas() {

    var W = $(window).width() - 380;   // zwraca szerokosc obszaru przeglądarki 
    var H = $(window).height();   // zwraca wysokosc obszaru przeglądarki 


    var SIZE = 800 + 200 * level;

    if (W > SIZE) W = SIZE;
    if (H > SIZE) H = SIZE;

    canvas.width = W;
    canvas.height = H;

    canvasWidth = W;
    canvasHeight = H;
}

function onKeydown(e) {

    if (player) {
        keys.onKeyDown(e);
    }

   if (pokazywanieWynikow) {
       schowajWyniki();
       return;
   }

    if (keys.esc) {

        if (czyHandel) {

            hideHandel();

        } else {

            startMenu();
        }
    }
}

function onKeyup(e) {
    if (player) {
        keys.onKeyUp(e);
    }
}

// aktualizacja danych i rysowanie w każdej klatce
function animate() {
    update();
    draw();
    window.frame(animate);

    ctrlDown = false;
}

function wyrzucMonety(px, py) {

    var coinsX = px + Math.floor(Math.random() * 40) - 20;
    var coinsY = py + Math.floor(Math.random() * 40) - 20;
    var coinsAmmount = 20;

    coins.push([coinsX, coinsY, coinsAmmount]);
}

function ustawMinicanvas(img) {

    miniCanvas.width = img.width / 4;
    miniCanvas.height = img.height / 4;
    miniCtx.drawImage(img, 0, 0);
}


function sprawdzInterakcje(obiekty, img, nazwa) {

    if (!gra) {
        return;
    }

    var px = playerPosition[0];
    var py = playerPosition[1];

    // aktualizacja przecwnikow
    for (var i = 0; i < enemies.length; i++) {

        // sprawdza czy przeciwnik jest ciągle żywy
        if (!enemies[i].alive()) {
            continue;
        }

        var enemyPos = enemies[i].getPos();
		
        var ex = enemyPos[0] + 40;
        var ey = enemyPos[1] + 40;

        var dx = Math.abs(ex - px);
        var dy = Math.abs(ey - py);

        // sprawdza czy przeciwnik nie jest w pobliżu gracza
        if (dx < 50 && dy < 50) {

            if (player.loseHP() && gra) {

                gra = false;
                etykieta("komunikat", "Przegrales");
                setTimeout(function () {
                    player.restart();

                    gra = true;
                }, 3000);
            }
            // utrata punktów życia gracza

            enemies[i].wyswietlPasekZycia();

            ustawMinicanvas(enemies[i].img());

            if (ctrlDown && character !== "ninja" && character !== "nekromanta" && enemies[i].loseHP(player.ileSily())) {

                // w przypadku kiedy przeciwnik akurat zginie (z funkcji loseHP zostanie zwrócone true, to dodatkowo gracz zyskuje doświadczenie i złoto)
                player.zyskajDoswiadczenie(20);
                wyrzucMonety(px, py);
                ctrlDown = false;
            }

            socket.emit('ileZycia', [i, enemies[i].ileZycia()]);
        }

        if (character == "nekromanta" || character == "lucznik") {

            var strzalX = Math.abs(ex - strzal[0]);
            var strzalY = Math.abs(ey - strzal[1]);

            // sprawdza czy strzal lucznika albo nekromanty nie jest w pobliżu gracza
            if (strzalX < 40 && strzalY < 40) {

                ustawMinicanvas(enemies[i].img());
                player.koniecStrzalu();

                if (enemies[i].loseHP(player.ileSily())) {

                    // w przypadku kiedy przeciwnik akurat zginie (z funkcji loseHP zostanie zwrócone true, to dodatkowo gracz zyskuje doświadczenie)
                    player.zyskajDoswiadczenie(20);

                    wyrzucMonety(px, py);
                }

                socket.emit('ileZycia', [i, enemies[i].ileZycia()]);
            }
        }
    }

    // sprawdzamy czy jestesmy w poblizu obiektow
    for (var i = 0; i < obiekty.length; i++) {

        var tx = obiekty[i][0] + img.width/2;
        var ty = obiekty[i][1] + img.height/2;

        // px - pozycja obiektu, tx - pozycja obiektu, dx - roznica odleglosci

        var cx = px + frameSize[character][0]/2;
        var cy = py + frameSize[character][1]/2;

        var odl = Math.sqrt( (tx - cx) * (tx - cx) + (ty - cy) * (ty - cy) );

        if (odl < (img.width/2) + 35) {

            miniCanvas.width = img.width;
            miniCanvas.height = img.height;
            miniCtx.drawImage(img, 0, 0);

            switch (nazwa) {

                case "rabanie":
                    rabanie = true;
                    break;
                case "lowienie":
                    lowienie = true;
                    break;
                case "wydobywanie":
                    wydobywanie = true;
                    break;
                case "monety":
                    zbieranieMonet = true;
                    break;
            }
        }

        // odleglosc od kursora myszy
        var mx = mouseX - tx + offX;
        var my = mouseY - ty + offY;


        if (mx > -15 && mx < img.width + 15 && my > -15 && my < img.width + 15) {

            switch (nazwa) {

                case "wydobywanie":
                    hoverKopalnia = true;
                    break;
                case "lowienie":
                    hoverStaw = true;
                    break;
                case "rabanie":
                    hoverDrzewo = true;
                    break;
                case "monety":
                    hoverMonety = true;
                    break;
            }
        }
    }
}

function update() {

    if (player === undefined) return;

    socket.emit('infoAboutPlayer', {

        nick:playerNick,
        nazwa:player.nazwa,
        x:player.getX(),
        y:player.getY(),
        dosw:player.ileDoswiadczenia(),
        zloto:player.ileZlota(),
        czyAtak: ctrlDown,
        strona : player.strona,
        zycie : player.ileZycia(),
        wspStrzalu: player.wspStrzalu()
    });

    var res = player.update(keys); // aktualizacja gracza
    playerPosition = [res[0], res[1]];
    strzal = res[2];
    framePos = player.framePos();

    var px = playerPosition[0];
    var py = playerPosition[1];

    miniCtx.clearRect(0, 0, miniCanvas.width, miniCanvas.height);

    document.getElementById("enemyHP").innerHTML = "";

    var sumaZyciaSmokow = 0;
    var sumaZyciaMalpoludow = 0;

    for (var i = 0; i < enemies.length; i++) {

        if (enemies[i].jakiRodzaj() === "smok") {

            if (enemies[i].ileZycia() > 0) {

                sumaZyciaSmokow += (enemies[i].ileZycia() | 0);
            }
        } else {

            if (enemies[i].ileZycia() > 0) {

                sumaZyciaMalpoludow += (enemies[i].ileZycia() | 0);
            }
        }
    }

    etykieta("smokiZycie", "Smoki: " + sumaZyciaSmokow);
    etykieta("malpoludyZycie", "Małpoludy: " + sumaZyciaMalpoludow);

    handel = false;
    dojenie = false;
    rabanie = false;
    lowienie = false;
    wydobywanie = false;

    // hover - najechanie myszką
    hoverDrzewo = false;
    hoverKopalnia = false;
    hoverStaw = false;
    hoverKrowa = false;
    hoverHandlarz = false;

    sprawdzInterakcje(trees, IMG.tree, "rabanie");
    sprawdzInterakcje(stawy, IMG.staw, "lowienie");
    sprawdzInterakcje(kopalnie, IMG.kopalnia, "wydobywanie");
    sprawdzInterakcje(coins, IMG.coins, "monety");

    // aktualizacja postaci, ktore nie sa wrogami
    for (var i = 0; i < NPCs.length; i++) {

        var pos = NPCs[i].pos();

        var tx = pos[0];
        var ty = pos[1];

        var dx = Math.abs(pos[0] - px);
        var dy = Math.abs(pos[1] - py);

        var img = NPCs[i].img();

        if (dx < 30 && dy < 30) {

            miniCanvas.width = img.width / 4;
            miniCanvas.height = img.height / 4;
            miniCtx.drawImage(NPCs[i].img(), 0, 0);

            handel = (NPCs[i].nazwa === "handlarz");
            dojenie = (NPCs[i].nazwa === "krowa");

        }

        // odleglosc od kursora myszy
        var mx = mouseX - tx + offX;
        var my = mouseY - ty + offY;

        if (mx > 0 && mx < img.width && my > 0 && my < img.width) {

            var cSel = $('#czynnosc');
            if (NPCs[i].nazwa === "handlarz") {
                hoverHandlarz = true;
                cSel.html("handel");
            }

            if (NPCs[i].nazwa === "krowa") {
                hoverKrowa = true;
                cSel.html("dojenie");
            }
        }
    }

    var cursor = 'auto';
    if (hoverMonety || hoverDrzewo || hoverKopalnia || hoverStaw || hoverKrowa || hoverHandlarz) {

        cursor = 'pointer';
    }
    $('canvas').css('cursor', cursor);

    zloto = player.ileZlota();
}

function drawRotatedImage(context, image, x, y, angle) {

    context.save();
    context.translate(x, y);
    context.rotate(angle);
    context.drawImage(image, -(image.width/2), -(image.height/2));
    context.restore();
}

function rysujObiekty(pos, img, offX, offY) {

    for (var i = 0; i < pos.length; i++) {

        var x = pos[i][0];
        var y = pos[i][1];

        viewCtx.drawImage(img, x - offX, y - offY)
    }
}

function draw() {

    if (player === undefined) return;

    var x = playerPosition[0] - (canvasWidth / 2);
    var y = playerPosition[1] - (canvasHeight / 2);
    if (x < 0) x = 0;
    if (y < 0) y = 0;

    if (x > map.w - canvas.width) x = map.w - canvas.width;
    if (y > map.h - canvas.height) y = map.h - canvas.height;

    offX = x;
    offY = y;

    // czyszczenie obszaru
    viewCtx.clearRect(0, 0, canvas.width, canvas.height);
    viewCtx.fillStyle = "#77aa77";
    viewCtx.fillRect(0, 0, canvas.width, canvas.height);
    viewCtx.fillStyle = "#dddddd";
    viewCtx.lineWidth = 6;
    viewCtx.rect(0, 0, canvas.width, canvas.height);
    viewCtx.stroke();

    rysujObiekty(trees, IMG.tree, offX, offY);
    rysujObiekty(stawy, IMG.staw, offX, offY);
    rysujObiekty(kopalnie, IMG.kopalnia, offX, offY);
    rysujObiekty(coins, IMG.coins, offX, offY);

    player.draw(viewCtx, offX, offY); // rysowanie gracza

    // rysowanie pozostałych postaci
    for (var i = 0; i < enemies.length; i++) {
        if (enemies[i].alive()) enemies[i].draw(viewCtx, offX, offY);
    }

    for (var i = 0; i < NPCs.length; i++) {
        NPCs[i].draw(viewCtx, offX, offY);
    }

    for (var i = 0; i < strzal.length / 2; i++) {

        if (player.nazwa == "nekromanta") {
            viewCtx.drawImage(IMG.fireNekro, strzal[0] - offX, strzal[1] - offX);
        } else if (player.nazwa = "lucznik") {

            drawRotatedImage(viewCtx, IMG.fireLucznik, strzal[0] - offX, strzal[1] - offY, Math.atan2(dyStrzalu, dxStrzalu));
        }
    }

    for (var key in otherPlayers) {
        if (otherPlayers.hasOwnProperty(key)) {

            if (key.length > 0 && key != playerNick) {

                var p = otherPlayers[key];
                var img = IMG[p.nazwa];

                var fx = frameSize[p.nazwa][0];
                var fy = frameSize[p.nazwa][1];

                if (p.zycie > 0.1) {
                    viewCtx.drawImage(img, 0, 0, fx, fy, p.x - offX, p.y - offY, fx, fy);
                }
                viewCtx.stroke();
            }
        }
    }
}

// funkcja odpowiedzialna za generowanie kolejnych klatek animacji (co 150ms)
window.frame = (function () {
    return function (callback) {
        window.setTimeout(callback, 200);
    };
})();


function ustawGracza(i) {

    whichCharacter = parseInt(i);
    character = characters[whichCharacter];
}

// obsługa przycisku nowej gry
function newGame() {


    socket.emit('newGame', 0);

    playerNick = $("#txt").val();
    socket.emit('playerList', 0);

    socket.on('playerList', function (playerList) {

        if (playerList.contains(playerNick)) {

            alert("Dany nick juz zostal uzyty w grze, wybierz inny");
        } else {

            setTimeout(function () {
                etykieta("nick", playerNick);
                etykieta("nickGracza", playerNick);

                $('#menu').hide();
                $('#content').show();
                ustaw();
                player = new Player(400, 400, getAttr(character), startoweZloto);
                gra = true;

            }, 1500);
        }
    });

}

function startMenu() {
    gra = false;
    $('#menu').show();
    $('#content').hide();
}

// obsługa kupowania
function kup(element, cena) {
    player.dodajWyposazenie(element, cena);
}

// podnoszenie umiejętności gracza
function umiejetnosc(cecha, ile) {

    player.podniesUmiejetnosc(cecha, ile);
}

function mouseMove(e) {

    mouseX = e.pageX - leftOffset;
    mouseY = e.pageY;

    $('#status').html(mouseX + ', ' + mouseY);

}

function mouseClick(e) {

    var mX = e.pageX - leftOffset;
    var mY = e.pageY;


    if (handel && hoverHandlarz) {

        handelMenu();
    }

    else if (rabanie && hoverDrzewo) {

        setTimeout(function () {
            player.rabanie();
        }, 1000);
    }

    else if (lowienie && hoverStaw) {

        setTimeout(function () {
            player.lowienie();
        }, 1000);

    } else if (wydobywanie && hoverKopalnia) {

        setTimeout(function () {
            player.wydobywanie();
        }, 1000);

    } else if (dojenie && hoverKrowa) {

        setTimeout(function () {
            player.dojenie();
        }, 1000);
    }
    else if (zbieranieMonet && hoverMonety) {

        player.zyskajZloto(20);
        coins = [];
        hoverMonety = false;
    }

    else if (character === "nekromanta" || character === "lucznik") {

        var px = playerPosition[0];
        var py = playerPosition[1];

        if (mX > 0) {
            player.strzelaj(px, py, mX, mY);
        }

        dxStrzalu = mX - (px + 20);
        dyStrzalu = mY - (py + 20);
    }
}

function rightClick() {

    if (czyHandel) {
        hideHandel();
    }
}

function handelMenu() {

    $('#handel').show();
    czyHandel = true;
}

function hideHandel() {

    $('#handel').hide();
    czyHandel = false;
}

$(function () {

    var ctrlKey = 17;

    $(document).keydown(function (e) {
        if (e.keyCode == ctrlKey) {

            ctrlDown = true;
            attackCtx.drawImage(IMG.attack, 0, 0);
        }
    }).keyup(function (e) {

        if (e.keyCode == ctrlKey) {

            ctrlDown = false;
            attackCtx.clearRect(0, 0, IMG.attack.width, IMG.attack.height);
        }
    });
});

function pokazWyniki() {

    pokazywanieWynikow = true;
    $("#wyniki").show();
    $("#menu").hide();

    socket.emit('wyniki', 0);
    socket.on('wyniki', function(dane) {

        dane.reverse();

        var content = "<table>";
        for (var i = 0; i < dane.length; i++) {
            content += "<tr> <td>" + dane[i][0] + "</td> <td>" + dane[i][1] + "</td> </tr>"
        }
        content += "</table>";

        $("#wyniki").html(content);
    });

}

function schowajWyniki() {

    $("#wyniki").hide();
    $("#menu").show();

    pokazywanieWynikow = false;
}